#include "zhi.h"
/*
 * 功能：内存管理器。负责内存的分配，扩容和释放。通过realloc来实现malloc、realloc和free 三种功能：1 申请内存；2 修改空间大小；3 释放内存。
 * 虚拟机S：虚拟机指针
 * ptr:是由malloc返回的地址或者是null,
 * 旧内存大小:原来申请的内存大小
 * 新内存大小:变更后的内存大小（新的内存大小）
 * */
void* 内存管理器(虚拟机* 虚拟机S, void* ptr, uint32_t 旧内存大小, uint32_t 新内存大小)
{
   //累计系统分配的总内存
   虚拟机S->系统已分配的总内存 += 新内存大小 - 旧内存大小;

    //避免realloc(NULL, 0)定义的新地址,此地址不能被释放
   if (新内存大小 == 0) {
      free(ptr);
      return NULL;
   }

   //在分配内存时若达到了GC触发的阀值则启动垃圾回收
   if (新内存大小 > 0 && 虚拟机S->系统已分配的总内存 > 虚拟机S->config.nextGC)
   {
      运行垃圾回收器(虚拟机S);
   }

   return realloc(ptr, 新内存大小);
}

// 找出大于等于v最近的2次幂（返回值是2的幂且大于或等于v）
uint32_t 大于等于v最近的2次幂(uint32_t v) {
   v += (v == 0);  //修复当v等于0时结果为0的边界情况
   v--;
   v |= v >> 1;
   v |= v >> 2;
   v |= v >> 4;
   v |= v >> 8;
   v |= v >> 16;
   v++;
   return v;
}

定义缓冲区方法M(ZiFuChuan)
定义缓冲区方法M(Int)
定义缓冲区方法M(Char)
定义缓冲区方法M(Byte)

void 清理符号表(虚拟机* 虚拟机S, SymbolTable* buffer) {
   uint32_t idx = 0;
   while (idx < buffer->count) {
      内存管理器(虚拟机S, buffer->数据缓冲区[idx++].str, 0, 0); 
   }
   ZiFuChuanBufferClear(虚拟机S, buffer);
}

//通用报错函数
void 错误报告(void* 词法分析器S, 错误类型E errorType, const char* fmt, ...)
{
   char buffer[默认缓冲区大小M] = {'\0'};
   va_list ap;
   va_start(ap, fmt);
   vsnprintf(buffer, 默认缓冲区大小M, fmt, ap);
   va_end(ap);

   switch (errorType) {
      case 错误_输入输出:     /*有关文件IO（输入输出）的错误*/
      case 错误_内存分配:    /*内存分配的错误*/
	 fprintf(stderr, "%s:%d In function %s():%s\n",
		 __FILE__, __LINE__, __FUNCTION__, buffer);
	 break;
      case 错误_词法分析:   /*词法分析的错误*/
      case 错误_编译: /*编译错误*/
	 ASSERT(词法分析器S != NULL, "词法分析器S is null!");
	 fprintf(stderr, "%s:%d \"%s\"\n", ((词法分析器*)词法分析器S)->源码文件名,
	       ((词法分析器*)词法分析器S)->前一个单词.行号, buffer);
	 break;
      case 错误_runtime: /*runtime错误。虚拟机运行阶段的错误*/
	    fprintf(stderr, "%s\n", buffer);
	 break;
      default:
	 没有达到M();
   }
   exit(1);
}
